package com.dh.leetcode.nine;

import org.junit.Assert;
import org.junit.Test;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * ClassName: _997_find_the_town_judge
 *
 * @author shouzimu
 * @Description: 997. 找到小镇的法官
 * 在一个小镇里，按从 1 到 n 为 n 个人进行编号。传言称，这些人中有一个是小镇上的秘密法官。
 * <p>
 * 如果小镇的法官真的存在，那么：
 * <p>
 * 小镇的法官不相信任何人。
 * 每个人（除了小镇法官外）都信任小镇的法官。
 * 只有一个人同时满足条件 1 和条件 2 。
 * 给定数组 trust，该数组由信任对 trust[i] = [a, b] 组成，表示编号为 a 的人信任编号为 b 的人。
 * <p>
 * 如果小镇存在秘密法官并且可以确定他的身份，请返回该法官的编号。否则，返回 -1。
 * <p>
 * 示例 1：
 * <p>
 * 输入：n = 2, trust = [[1,2]]
 * 输出：2
 * 示例 2：
 * <p>
 * 输入：n = 3, trust = [[1,3],[2,3]]
 * 输出：3
 * 示例 3：
 * <p>
 * 输入：n = 3, trust = [[1,3],[2,3],[3,1]]
 * 输出：-1
 * 示例 4：
 * <p>
 * 输入：n = 3, trust = [[1,2],[2,3]]
 * 输出：-1
 * 示例 5：
 * <p>
 * 输入：n = 4, trust = [[1,3],[1,4],[2,3],[2,4],[4,3]]
 * 输出：3
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/find-the-town-judge
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * @date 2021/12/19 09:27
 */
public class _997_find_the_town_judge {

    public int findJudge2(int n, int[][] trust) {
        int res = -1;
        Map<Integer, Set<Integer>> bucket = new HashMap<>();
        for (int[] ints : trust) {
            Set<Integer> set = bucket.getOrDefault(ints[0], new HashSet<>());
            set.add(ints[1]);
            bucket.put(ints[0], set);
        }
        int i = 0;
        for (int integer = 1; integer <= n; integer++) {
            if (null == bucket.get(integer)) {
                res = integer;
                i++;
            }
            if (i > 1) {
                return -1;
            }
        }
        if (res != -1) {
            for (Integer integer : bucket.keySet()) {
                Set set = bucket.get(integer);
                if (integer != res && null != set && !set.contains(res)) {
                    return -1;
                }
            }
        }

        return res;
    }


    /**
     *
     * 入度为 N-1
     * 出度为0
     *
     * @param n
     * @param trust
     * @return
     */
    public int findJudge(int n, int[][] trust) {
        int[] from = new int[n + 1];
        int[] to = new int[n + 1];

        for (int[] ints : trust) {
            from[ints[0]]++;
            to[ints[1]]++;
        }

        for (int i = 1; i <= n; i++) {
            if (from[i] == 0 && to[i] == n - 1) {
                return i;
            }
        }
        return -1;
    }

    @Test
    public void findJudgeTest() {
        Assert.assertEquals(1, findJudge(1, new int[][]{}));
        Assert.assertEquals(3, findJudge(3, new int[][]{{1, 3}, {2, 3}}));
        Assert.assertEquals(-1, findJudge(3, new int[][]{{1, 2}, {2, 3}}));
        Assert.assertEquals(-1, findJudge(3, new int[][]{{1, 3}, {2, 3}, {3, 1}}));
        Assert.assertEquals(2, findJudge(2, new int[][]{{1, 2}}));
    }
}
